import { OperationType, recordOperateLogFunc } from "@/api/log";
import {
  Company,
  CompanyDependency,
  createDepartment,
  deleteDepartment,
  Department,
  getCompanyData,
  getCompanyDepTree,
  getCompanyList,
  getDepartmentData,
  updateDepartment
} from "@/api/system-manage/org";
import { clone } from "@/utils";
import {
  getCurrentInstance,
  onMounted,
  reactive,
  Ref,
  ref,
  watch
} from "@vue/composition-api";
import { Message, MessageBox } from "element-ui";

const recordOperateLog = recordOperateLogFunc("系统管理", "组织管理");

// 当前详情的数据结构是否是公司还是部门
const isCompany = ref(true);

// 当前选择公司的ID
const selectedCompanyId = ref("");

// 刷新公司关系树状图
let refreshCompanyTree: () => void;

// 刷新详情
let refreshDetail: () => void;

// 当前详情数据结构
const detail: Ref<Company | Department> = ref({
  aaddress: "",
  ccity: {
    id: 0,
    name: "",
    province: {
      id: 0,
      name: ""
    }
  },
  ccompany: "",
  companytype: 0,
  contacter: "",
  contactway: "",
  id: "",
  isdel: 0,
  ppostcode: "",
  remark: ""
});

export function useCompanyData() {
  // 公司列表
  const companyList: Ref<Company[]> = ref([]);

  // 公司依赖结构树
  const companyDepTree: Ref<ElTree[]> = ref([]);
  const companyDepTreeLoading = ref(false);

  onMounted(async () => {
    const data = await getCompanyList();
    if (data) {
      companyList.value = data;
    }
  });

  refreshCompanyTree = async () => {
    companyDepTreeLoading.value = true;
    // 这里获得数组结构的依赖关系,需要转换成树结构.
    const arrayDeps = await getCompanyDepTree(selectedCompanyId.value);
    if (arrayDeps) {
      companyDepTree.value = convertDepArrayToTree(arrayDeps);
    }

    companyDepTreeLoading.value = false;
    recordOperateLog(OperationType.Select);
  };

  watch(selectedCompanyId, refreshCompanyTree);

  return {
    companyList,
    selectedCompanyId,

    companyDepTree,
    companyDepTreeLoading
  };
}

export function useDetail() {
  const id = ref("");

  async function handleSelectCompany(node, { level }) {
    let data: Department | Company | false = false;

    id.value = node.id;

    // 根节点获取的是公司数据
    if ((level as number) === 1) {
      data = await getCompanyData(node.id);
      isCompany.value = true;
    } else {
      data = await getDepartmentData(node.id);
      isCompany.value = false;
    }

    if (data) {
      detail.value = data;
    }
  }

  refreshDetail = async () => {
    let data: Department | Company | false = false;
    if (isCompany.value) {
      data = await getCompanyData(id.value);
    } else {
      data = await getDepartmentData(id.value);
    }
    if (data) {
      detail.value = data;
    }
    recordOperateLog(OperationType.Detail);
  };

  return {
    detail,
    isCompany,
    handleSelectCompany
  };
}

export function useEditor() {
  const editor = reactive({
    show: false,
    target: {} as any | Department
  });

  const that = getCurrentInstance();

  function handleOpenEditorWindow() {
    if (isCompany.value) {
      Message.error("无法修改公司信息。");
      return;
    }

    const currentDepartment = detail.value as Department;

    editor.target = clone(currentDepartment);
    // shortcpname 改成公司名
    editor.target.shortcpname = currentDepartment.shortcpname.id;
    editor.target.cpname = currentDepartment.shortcpname.ccompany;
    if (currentDepartment.pdeptid) {
      // pdeptid 改成部门名称
      editor.target.pdeptid = currentDepartment.pdeptid.id;
      editor.target.pdeptname = currentDepartment.pdeptid.deptname;
    } else {
      editor.target.pdeptid = "";
      editor.target.pdeptname = "";
    }

    editor.show = true;
  }

  /**
   * 检查修改表单
   */
  function handleCheckEditorForm() {
    (that.refs.editorForm as any).submit();
  }

  /**
   * 提交修改表单
   */
  async function handleSubmitEditorForm() {
    const result = await updateDepartment(editor.target);
    if (result) {
      Message.success(result);
      refreshDetail();
      editor.show = false;
      recordOperateLog(OperationType.Update);
    }
  }

  return {
    editor,
    handleOpenEditorWindow,
    handleCheckEditorForm,
    handleSubmitEditorForm
  };
}

export function useAddit() {
  const addit = reactive({
    show: false,
    target: {} as any | Department
  });
  const that = getCurrentInstance();

  function hadnleOpenAdditWindow() {
    addit.target = {
      deptname: "",
      shortcpname: "",
      pdeptid: "",
      contactor: "",
      contactway: "",
      remark: ""
    };

    // 如果选择是公司, 那么是没有上级部门的
    if (isCompany.value) {
      const currentCompany = detail.value as Company;

      // 如果没有选中公司id长度为0
      if (currentCompany.id.length === 0) {
        return;
      }

      addit.target.shortcpname = currentCompany.id;
      addit.target.cpname = currentCompany.ccompany;

      // pdeptid 只为空
      addit.target.pdeptid = "";
      addit.target.pdeptname = "";
    } else {
      const currentDepartment = detail.value as Department;

      // shortcpname 改成公司名
      addit.target.shortcpname = currentDepartment.shortcpname.id;
      addit.target.cpname = currentDepartment.shortcpname.ccompany;
      // pdeptid 改成当前部门名称
      addit.target.pdeptid = currentDepartment.id;
      addit.target.pdeptname = currentDepartment.deptname;
    }

    addit.show = true;
  }

  /**
   * 检查新增表单
   */
  function handleCheckAdditForm() {
    (that.refs.additForm as any).submit();
  }

  /**
   * 提交新增表单
   */
  async function handleSubmitAdditForm() {
    const result = await createDepartment(addit.target);
    if (result) {
      Message.success("创建部门成功");
      // 这个要刷新公司结构树
      refreshCompanyTree();
      addit.show = false;
      recordOperateLog(OperationType.Add);
    }
  }

  return {
    addit,

    hadnleOpenAdditWindow,
    handleCheckAdditForm,
    handleSubmitAdditForm
  };
}

/**
 * 删除部门
 */
export function handleDeleteDepartment() {
  if (isCompany.value) {
    Message.error("不可删除公司");
    return;
  }

  const currentDepartment = detail.value as Department;

  MessageBox.confirm(`真的要删除${currentDepartment.deptname}么`, "提示", {
    type: "warning"
  }).then(async () => {
    const result = await deleteDepartment(currentDepartment.id);
    if (result) {
      Message.success(result);
      refreshCompanyTree();
      // 删除部门后详情置空
      detail.value = {
        deptname: "",
        contactor: "",
        contactway: "",
        remark: ""
      } as any;
      recordOperateLog(OperationType.Delete);
    }
  });
}

/**
 * 将数组依赖关系转化为ElementUI可用的Tree型结构
 */
function convertDepArrayToTree(list: CompanyDependency[]): ElTree[] {
  const tree: ElTree = {
    id: "",
    label: "",
    children: []
  };

  // 找出pid为0的节点,为整个树的根节点
  const rootNode = list.filter(t => t.pId === 0)[0];
  // 找出所有的子节点
  const subNodes = list.filter(t => t.pId !== 0);

  console.log("根节点为:", rootNode);

  tree.id = rootNode.id;
  tree.label = rootNode.name;

  let cycleCount = 1;

  /**
    考虑到节点乱序的清情况, 排在前面的节点可能需要依赖排在后面父节点才能插入,
    如果出现这种情况就跳过该节点, 等待下次循环再进行插入, 每次插入都移除成功插入的节点.
    直到数组为空，也就是所有节点都成功插入

    P.S. 如果存在 *没有父节点或者找不到父节点的节点* 这个函数会进入死循环，需要修复数据库的脏数据
  */
  while (subNodes.length > 0) {
    for (let i = 0; i < subNodes.length; i++) {
      if (insertToTreeById(subNodes[i], tree)) {
        console.log("该节点插入成功, 弹出:" + subNodes[i].name);
        // 如果成功插入, 就去掉这个节点
        subNodes.splice(i, 1);
        // 节点去掉之后后续节点的索引都会-1, 这里i也得-1
        i--;
      } else {
        console.log("该节点未插入成功, 等待下次循环:" + subNodes[i].name);
      }
    }

    console.log(
      "第" + cycleCount++ + "次节点循环结束, 剩余节点数量:" + subNodes.length
    );
  }

  return [tree];
}

/**
  根据node参数的父节点信息在tree寻找合适插入节点的位置, 成功插入返回true 否则
*/
function insertToTreeById(node: CompanyDependency, tree: ElTree): boolean {
  // 如果该树的ID等于节点标识的父ID 直接插入
  if (tree.id === node.pId) {
    console.log("找到该父节点了", tree);
    tree.children.push({
      id: node.id,
      label: node.name,
      children: []
    });

    return true;
  }

  for (let i = 0; i < tree.children.length; i++) {
    console.log("进入下一层寻找", tree.children[i]);
    if (insertToTreeById(node, tree.children[i])) {
      return true;
    }
  }

  console.log("该层未找到:" + tree.label);
  return false;
}
